using System.Collections.Generic;
using InterfaceWeaver.AopCore;
using Roslyn.Compilers.CSharp;

namespace InterfaceWeaver.CustomTool
{
    public class GenericSkipAspectHandler : IAspectHandler
    {
        /// <summary>
        /// Handles the on namespace.
        /// </summary>
        /// <param name="dispatcher">The context.</param>
        /// <param name="attributeSyntax">The attribute syntax.</param>
        /// <param name="namespaceDeclarationSyntax">The namespace declaration syntax.</param>
        /// <returns>
        /// True if the aspect is handled, false otherwise
        /// </returns>
        public bool HandleOnNamespace(AspectDispatcher dispatcher, AttributeSyntax attributeSyntax,
                                      NamespaceDeclarationSyntax namespaceDeclarationSyntax)
        {
            return attributeSyntax.IsOfType<SkipImplementINotifyPropertyChangedAttribute>()
                || attributeSyntax.IsOfType<SkipInheritAttribute>()
                || attributeSyntax.IsOfType<SkipMapCommandAttribute>()
                || attributeSyntax.IsOfType<SkipMapDependencyPropertyAttribute>()
                || attributeSyntax.IsOfType<SkipSetterChecksChangeAttribute>()
                || attributeSyntax.IsOfType<SkipHookGenericPropertySetAttribute>()
                || attributeSyntax.IsOfType<SkipHookSpecificPropertySetAttribute>()
                || attributeSyntax.IsOfType<SkipAddPropertyNameConstantAttribute>();
        }

        /// <summary>
        /// Determines whether the aspect is known and could be handled by aspect handler.
        /// </summary>
        /// <param name="dispatcher">The context.</param>
        /// <param name="attributeSyntax">The attribute syntax.</param>
        /// <returns></returns>
        public bool HandleOnInterfacePreview(AspectDispatcher dispatcher, AttributeSyntax attributeSyntax)
        {
            return attributeSyntax.IsOfType<SkipImplementINotifyPropertyChangedAttribute>()
                || attributeSyntax.IsOfType<SkipInheritAttribute>()
                || attributeSyntax.IsOfType<SkipMapCommandAttribute>()
                || attributeSyntax.IsOfType<SkipMapDependencyPropertyAttribute>()
                || attributeSyntax.IsOfType<SkipSetterChecksChangeAttribute>()
                || attributeSyntax.IsOfType<SkipHookGenericPropertySetAttribute>()
                || attributeSyntax.IsOfType<SkipHookSpecificPropertySetAttribute>()
                || attributeSyntax.IsOfType<SkipAddPropertyNameConstantAttribute>();
        }

        /// <summary>
        /// Regarding all the handler answering preview step, this step determines whether there are some aspect handler that should be removed from next live cycle.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="attributeSyntax">The attribute syntax.</param>
        /// <param name="indirectAspectHandler"> </param>
        /// <param name="indirectAttributeSyntax"> </param>
        /// <returns></returns>
        public bool IsIndirectAspectsCompliantOnInterface(AspectDispatcher context, AttributeSyntax attributeSyntax, IAspectHandler indirectAspectHandler, AttributeSyntax indirectAttributeSyntax)
        {
            return !(
                (attributeSyntax.IsOfType<SkipImplementINotifyPropertyChangedAttribute>() && indirectAttributeSyntax.IsOfType<ImplementINotifyPropertyChangedAttribute>())
                || (attributeSyntax.IsOfType<SkipInheritAttribute>() && indirectAttributeSyntax.IsOfType<InheritAttribute>())
                || (attributeSyntax.IsOfType<SkipMapCommandAttribute>() && indirectAttributeSyntax.IsOfType<MapCommandAttribute>())
                || (attributeSyntax.IsOfType<SkipMapDependencyPropertyAttribute>() && indirectAttributeSyntax.IsOfType<MapDependencyPropertyAttribute>())
                || (attributeSyntax.IsOfType<SkipSetterChecksChangeAttribute>() && indirectAttributeSyntax.IsOfType<CheckSetterHasChangesAttribute>())
                || (attributeSyntax.IsOfType<SkipHookGenericPropertySetAttribute>() && indirectAttributeSyntax.IsOfType<HookGenericPropertySetAttribute>())
                || (attributeSyntax.IsOfType<SkipHookSpecificPropertySetAttribute>() && indirectAttributeSyntax.IsOfType<HookSpecificPropertySetAttribute>())
                || (attributeSyntax.IsOfType<SkipAddPropertyNameConstantAttribute>() && indirectAttributeSyntax.IsOfType<AddPropertyNameConstantAttribute>())
                );
        }

        /// <summary>
        /// Gets the handling priority on interface.
        /// </summary>
        /// <param name="dispatcher">The dispatcher.</param>
        /// <param name="attributeSyntax">The attribute syntax.</param>
        /// <param name="interfaceDeclarationSyntax">The interface declaration syntax.</param>
        /// <returns></returns>
        public AspectHandlingPriority GetHandlingPriorityOnInterface(AspectDispatcher dispatcher, AttributeSyntax attributeSyntax, InterfaceDeclarationSyntax interfaceDeclarationSyntax)
        {
            return AspectHandlingPriority.Normal;
        }

        /// <summary>
        /// Handles the on interface.
        /// </summary>
        /// <param name="dispatcher">The context.</param>
        /// <param name="attributeSyntax">The attribute syntax.</param>
        /// <param name="interfaceDeclarationSyntax">The interface declaration syntax.</param>
        /// <returns>
        /// True if the aspect is handled, false otherwise
        /// </returns>
        public void HandleOnInterface(AspectDispatcher dispatcher, AttributeSyntax attributeSyntax, InterfaceDeclarationSyntax interfaceDeclarationSyntax)
        {
        }

        /// <summary>
        /// Determines whether the aspect is known and could be handled by aspect handler.
        /// </summary>
        /// <param name="context"> </param>
        /// <param name="attributeSyntax">The attribute syntax.</param>
        /// <returns></returns>
        public bool HandleOnPropertyPreview(AspectDispatcher context, AttributeSyntax attributeSyntax)
        {
            return attributeSyntax.IsOfType<SkipImplementINotifyPropertyChangedAttribute>()
                || attributeSyntax.IsOfType<SkipInheritAttribute>()
                || attributeSyntax.IsOfType<SkipMapCommandAttribute>()
                || attributeSyntax.IsOfType<SkipMapDependencyPropertyAttribute>()
                || attributeSyntax.IsOfType<SkipSetterChecksChangeAttribute>()
                || attributeSyntax.IsOfType<SkipHookGenericPropertySetAttribute>()
                || attributeSyntax.IsOfType<SkipHookSpecificPropertySetAttribute>()
                || attributeSyntax.IsOfType<SkipAddPropertyNameConstantAttribute>();
        }

        /// <summary>
        /// Regarding all the handler answering preview step, this step determines whether there are some aspect handler that should be removed from next live cycle.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="attributeSyntax">The attribute syntax.</param>
        /// <param name="indirectAspectHandler"> </param>
        /// <param name="indirectAttributeSyntax"> </param>
        /// <returns></returns>
        public bool IsIndirectAspectsCompliantOnProperty(AspectDispatcher context, AttributeSyntax attributeSyntax, IAspectHandler indirectAspectHandler, AttributeSyntax indirectAttributeSyntax)
        {
            return !(
                (attributeSyntax.IsOfType<SkipImplementINotifyPropertyChangedAttribute>() && indirectAttributeSyntax.IsOfType<ImplementINotifyPropertyChangedAttribute>())
                || (attributeSyntax.IsOfType<SkipInheritAttribute>() && indirectAttributeSyntax.IsOfType<InheritAttribute>())
                || (attributeSyntax.IsOfType<SkipMapCommandAttribute>() && indirectAttributeSyntax.IsOfType<MapCommandAttribute>())
                || (attributeSyntax.IsOfType<SkipMapDependencyPropertyAttribute>() && indirectAttributeSyntax.IsOfType<MapDependencyPropertyAttribute>())
                || (attributeSyntax.IsOfType<SkipSetterChecksChangeAttribute>() && indirectAttributeSyntax.IsOfType<CheckSetterHasChangesAttribute>())
                || (attributeSyntax.IsOfType<SkipHookGenericPropertySetAttribute>() && indirectAttributeSyntax.IsOfType<HookGenericPropertySetAttribute>())
                || (attributeSyntax.IsOfType<SkipHookSpecificPropertySetAttribute>() && indirectAttributeSyntax.IsOfType<HookSpecificPropertySetAttribute>())
                || (attributeSyntax.IsOfType<SkipAddPropertyNameConstantAttribute>() && indirectAttributeSyntax.IsOfType<AddPropertyNameConstantAttribute>())
                );
        }

        /// <summary>
        /// Gets the handling priority on property.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="attributeSyntax">The attribute syntax.</param>
        /// <param name="propertyDeclarationSyntax">The property declaration syntax.</param>
        /// <returns></returns>
        public AspectHandlingPriority GetHandlingPriorityOnProperty(AspectDispatcher context, AttributeSyntax attributeSyntax, PropertyDeclarationSyntax propertyDeclarationSyntax)
        {
            return AspectHandlingPriority.Normal;
        }

        /// <summary>
        /// Handles the on member.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="attributeSyntax">The attribute syntax.</param>
        /// <param name="propertyDeclarationSyntax"> </param>
        /// <param name="handlerStreams"> </param>
        /// <returns>
        /// True if the aspect is handled, false otherwise
        /// </returns>
        public void HandleOnProperty(AspectDispatcher context, AttributeSyntax attributeSyntax, PropertyDeclarationSyntax propertyDeclarationSyntax, IDictionary<PropertyDeclarationSyntax, AspectTuple[]> handlerStreams)
        {
        }
    }
}